package pri.hillchen.std.nio.bio.chat;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

import static pri.hillchen.std.nio.bio.chat.BioServer.clientEndFlag;
import static pri.hillchen.std.nio.bio.chat.BioServer.msgEndFlag;

/**
 * @author:hillchen
 * @DESCRIPTION:
 * @Date: Created in 16:57 2018/3/5 0005./b
 */
public class BioClient {
    private final String name;
    private boolean stop = true;


    class SendThread implements Runnable{
        final BufferedWriter bw;
        final CountDownLatch mainWaitLatch;

        public SendThread(Socket socket,CountDownLatch mainWaitLatch) throws IOException {
            this.bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
            bw.write(name);
            bw.newLine();
            bw.write(msgEndFlag);
            bw.newLine();
            bw.flush();
            this.mainWaitLatch = mainWaitLatch;
        }

        public void run() {
            try{
                while (!stop){
                    Scanner scan = new Scanner(System.in);
                    String msg = scan.nextLine();
                    bw.write(msg);
                    bw.newLine();
                    bw.write(msgEndFlag);
                    bw.newLine();
                    bw.flush();
                    if(clientEndFlag.equals(msg)){
                        stop();
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                stop = true;
                mainWaitLatch.countDown();
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    class ReciveThread implements Runnable{
        private final BufferedReader br;
        final CountDownLatch mainWaitLatch;
        public ReciveThread(Socket socket,CountDownLatch mainWaitLatch) throws IOException {
            this.br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
            this.mainWaitLatch = mainWaitLatch;
        }
        public String read() throws IOException {
            StringBuilder sb = new StringBuilder();
            String line ;
            int lineNo = 0;
            while (!msgEndFlag.equals(line = br.readLine())){
                if(lineNo != 0){
                    sb.append("\n");
                }
                sb.append(line);
                lineNo++;
            }
            return sb.toString();
        }

        public void run() {
            while (!stop){
                try {
                    String msg = read();
                    if(clientEndFlag.equals(msg)){
                        stop();
                    }
                    System.out.println(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    stop();
                    mainWaitLatch.countDown();
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public BioClient(String name) {
        this.name = name;
    }

    public void start() throws IOException, InterruptedException {

        this.stop = false;
        Socket client  =  new Socket("localhost", 38080);
        CountDownLatch mainWaitLatch = new CountDownLatch(2);

        new Thread(new SendThread(client,mainWaitLatch)).start();
        new Thread(new ReciveThread(client,mainWaitLatch)).start();
        mainWaitLatch.await();
        client.shutdownOutput();
        client.shutdownInput();
        client.close();
    }
    public void stop(){
        this.stop = true;
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        String name = args != null && args.length>0 && args[0]!=null ? args[0] : "hillchen";
        new BioClient(name).start();
    }
}
